package tests;


import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import primitive3D.Cube;
import primitive3D.Pyramid;
import primitive3D.Sphere;
import rayCaster.Scene;
import static rayCaster.ApplicationInterface.*;
import static java.lang.Math.*;

public class TestCommandLine {

	/**
	 * @param args
	 */
	private String outputFile;
	private String inputFile;
	private int width;
	private int height;
	private double fob;
	private COLOR_OPTIONS colorMode;
	private COLOR_VAR_OPTIONS colorVariationMode;
	private boolean timeMeasuringMode;
	
	public static void main(String[] args) {
		TestCommandLine test = new TestCommandLine();		
		String stringValue = null;
		
		test.setDefaults();
		
		
		for(int i=0 ; i<args.length; i++){
			if( args[i].charAt(0) == '-' ){				 
				int index = test.getParamIndex( args[i].substring(1) );
				String option = args[i];
				System.out.println("i="+i+" ,  "+"index = "+index+"  ,  arg len="+args.length);
				System.out.println("switch="+option.substring(1));
				
				if( test.isUnarySwitch(index) )
					stringValue = null;
				else{
					if( args[i+1].charAt(0) == '-'){
						System.out.println("El switch " + option + " esperaba un parametro. SHOW Usage..");
						return;
					}else{
						stringValue = args[i+1].substring(0);
						i++;
					}
				}	
				System.out.println("value="+stringValue);
			 
				
				switch( index ){
					case 0: test.setInputFile( stringValue ); break;
					case 1: test.setOutputFile( stringValue ); break;
					case 2: String[] dimensions = test.getDimensions(stringValue);
							for( int k=0 ; k<dimensions.length ; k++)
								System.out.println(dimensions[k]);
							test.setWidth( dimensions[0] );
							test.setHeight( dimensions[1] ); break;
					case 3: test.setFob( stringValue ); break;
					case 4: test.setColorMode( stringValue ); break;
					case 5: test.setColorVariationMode( stringValue ); break;
					case 6: test.setTimeMeasuringMode( stringValue ); break;
					default: System.out.println("El switch "+option+" no es valido. Show USAGE ...");return;
				}				
			}else{
				System.out.println("Error en la sintaxis del comando: Show Usage ...");
			}
		}
		test.ShowParams();
		
		Scene scene = null;
		try {
			scene = test.loadScene();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	System.out.println(scene);
		
	}
	
	private void setDefaults() {
		inputFile = "scene1.sc";
		outputFile = OUT_FILE;
		width = WIDTH;
		height = HEIGHT;
		fob = ceil(VISUAL_ANGLE*180/PI);
		colorMode = COLOR_OPTIONS.RANDOM;
		colorVariationMode = COLOR_VAR_OPTIONS.LINEAR;
		timeMeasuringMode = false;		
	}

	private Scene loadScene() throws Exception {
		Scene scene = new Scene();
		
		for( int i=0 ; i< scenesList.length; i++){
			if( inputFile.compareTo(scenesList[i]) == 0 ){
				switch(i){
				case 0 : buildSceneOne( scene ); break;
				case 1 : buildSceneTwo( scene ); break;
				case 2 : buildSceneThree( scene ); break;
				}
			}				
		}
		
		return scene;
	}
	
	private void buildSceneOne(Scene scene) throws Exception {
		//Central pyramid with side 5
		Pyramid pyramid = new Pyramid();
		pyramid.scale(5);
		pyramid.setPosition(new Point3d(0,0,5.0/3.0));
		
		//Central sphere just above the pyramid
		Sphere centralSphere = new Sphere();
		centralSphere.setPosition(new Point3d(0, 0, 6));
			
		
		//4 spheres at distance 3 from the pyramid vertices
		Sphere sphere1=null;
		Sphere sphere2=null;
		Sphere sphere3=null;
		Sphere sphere4=null;
		
		sphere1 = new Sphere(0.5);
		sphere2 = new Sphere(0.5);
		sphere3 = new Sphere(0.5);
		sphere4 = new Sphere(0.5);			
		
		/* The four spheres are positioned in a square of vertices that
		 * are the vertices of the pyramid base but scaled. So, we
		 * calculate the distance from origin to the vertices secaled
		 * and the distance for coordinates X and Y are the rectangular
		 * components
		 */
		double distFromOrigin = (5*sqrt(2)/2) + 3;
		double dist = distFromOrigin/sqrt(2);
		
		sphere1.setPosition(new Point3d( dist, dist, 0.5 ) );
		sphere2.setPosition(new Point3d( -dist, dist, 0.5 ) );
		sphere3.setPosition(new Point3d( dist, -dist, 0.5) );
		sphere4.setPosition(new Point3d( -dist, -dist, 0.5) );
				
		//Add all objects
		scene.add(pyramid);
		scene.add(centralSphere);
		scene.add(sphere1);
		scene.add(sphere2);
		scene.add(sphere3);
		scene.add(sphere4);
		return;
	}

	
	private void buildSceneTwo(Scene scene) throws Exception {
		/* 4 spheres with radius 0.5 separated 1.5 from each other
		 * That means 4 points separated 1.5 => 3*1.5 = 4.5
		 * Then the position of the most upper left should be 4.5/2 = 2.25
		 */
		int cantSpheresPerSide = 4;
		double sphereRadius = 0.5;
		double separation = 1.5;		
		int jumps = cantSpheresPerSide-1;
		
		double totalDistance = jumps*separation;
		double coordinateInitialNumber = totalDistance/2;
		
		Point3d startingPoint = new Point3d(-coordinateInitialNumber, coordinateInitialNumber, -coordinateInitialNumber);
		Vector3d deltaX = new Vector3d(separation, 0, 0);
		Vector3d deltaY = new Vector3d(0, -separation, 0);
		Vector3d deltaZ = new Vector3d(0, 0, separation);
		
		for( int k=0 ; k<cantSpheresPerSide ; k++ ){
			Point3d pivoteZ = new Point3d(startingPoint);
			pivoteZ.scaleAdd(k, deltaZ, startingPoint);
			for( int i=0 ; i<cantSpheresPerSide ; i++ ){
				Point3d pivoteY = new Point3d();
				pivoteY.scaleAdd(i, deltaY, pivoteZ);
				for( int j=0 ; j<cantSpheresPerSide ; j++ ){					
						Point3d currentPoint = new Point3d();
						currentPoint.scaleAdd(j, deltaX, pivoteY);												
						scene.add(new Sphere(currentPoint,sphereRadius));
				}				
			}
		}
		
	}
	
	private void buildSceneThree(Scene scene) throws Exception {
		double side = 2;
		double radius = 1;
		double separation = 0.5;
		//The cube base must lay on the XY plane
		Cube centralCube = new Cube(side,new Point3d(0,0,side/2));
				
		//Sphere must lay on the XY plane
		double rightSpherePosX = side/2+radius+separation;  
		Sphere rightSphere = new Sphere(new Point3d(rightSpherePosX, 0 , radius/2),radius);
		
		double rightCubePosX = rightSpherePosX + radius + side/2+separation;
		Cube rightCube = new Cube(side,new Point3d(rightCubePosX, 0, side/2));
		
		Sphere leftSphere = new Sphere( new Point3d(-rightSpherePosX, 0, radius/2), radius);
		Cube leftCube = new Cube( side, new Point3d(-rightCubePosX, 0, side/2));
		
		scene.add(centralCube);
		scene.add(leftSphere);
		scene.add(leftCube);
		scene.add(rightSphere);
		scene.add(rightCube);		
	}
	
	private boolean isUnarySwitch(int index) {
		return index == 6;
	}

	private void setTimeMeasuringMode(String stringValue) {
		timeMeasuringMode = true;
	}

	private String[] getDimensions(String stringValue) {
		String[] dimensions = stringValue.split("x");
		return dimensions;
		
	}

	//For debugging
	private void ShowParams() {
		System.out.println("input = "+inputFile+"\toutput = "+outputFile);
		System.out.println("width = "+width+"\theight = "+height);
		System.out.println("fob = "+fob);
		System.out.println("colormode = "+colorMode+"\tcolorVariationMode="+colorVariationMode);
		System.out.println("time = " + timeMeasuringMode);
	}

	private void setColorVariationMode(String stringValue) {		
		if( stringValue.compareTo("linear") == 0 )
			colorVariationMode = COLOR_VAR_OPTIONS.LINEAR;
		else if( stringValue.compareTo("log") == 0 )
			colorVariationMode = COLOR_VAR_OPTIONS.LOG;
	}

	private void setColorMode(String stringValue) {
		if( stringValue.compareTo("random") == 0 )
			colorMode = COLOR_OPTIONS.RANDOM;
		else if( stringValue.compareTo("ordered") == 0 )
			colorMode = COLOR_OPTIONS.ORDERED;		
	}

	private  void setFob(String stringValue) {
		fob = Double.parseDouble(stringValue.trim());
		fob = fob * PI/180;		 
		
	}

	private void setHeight(String stringValue) {
		height = Integer.parseInt(stringValue.trim());
		System.out.println("height="+height);
	}

	private void setWidth(String stringValue) {
		width = Integer.parseInt(stringValue.trim());
		System.out.println("width="+width);
	}

	private void setInputFile(String stringValue) {
		inputFile = new String(stringValue);
	}

	private void setOutputFile(String stringValue) {
		outputFile = new String(stringValue);
	}

	public int getParamIndex(String string) {
		
		for(int i=0 ; i<validSwitches.length ; i++){
			if( string.compareTo(validSwitches[i]) == 0 ) 
					return i;
		}
		return -1;
	}
	 
}	
	
